const final = function(status, value) {
  let fn, isFulfilled;
  // 如果还是等待状态则直接返回
  if (this._status !== "PENDING") return;
  
  setTimeout(() => {
    this._status = status;
    isFulfilled = this._status === "FULFILLED";
    let queue = this[isFulfilled ? "_resolves" : "_rejects"];
    while ((fn = queue.shift())) {
      value = fn.call(this, value) || value;
    }

    this[isFulfilled ? "_value" : "_reason"] = value;
    this["_resolves"] = this["_rejects"] = undefined;
  });
};

/**
 * Promise
 * @param {Function} resolver 参数是一个函数，内部提供两个函数作为该函数的参数,分别是resolve 和 reject
 */
function Promise(resolver) {
  if (!(typeof resolver === "function"))
    throw new TypeError(
      "第一个参数必须是函数，函数接受俩个参数分别是，resolve 和 reject"
    );
  //如果不是promise实例，就new一个
  if (!(this instanceof Promise)) return new Promise(resolver);
  const promise = this;
  // 成功返回值，then用到
  promise._value;
  // 失败返回值，catch用到
  promise._reason;
  // 当前promise状态
  promise._status = "PENDING";
  // 存储状态
  promise._resolves = [];
  promise._rejects = [];

  function resolve(value) {
    final.apply(promise, ["FULFILLED"].concat([value]));
  }
  function reject(reason) {
    final.apply(promise, ["REJECTED"].concat(reason));
  }

  resolver.call(this, resolve, reject);
}
/**
 * then
 * @param {Function} onFulfilled 成功函数
 * @param {Function} onRejected 失败函数
 */
Promise.prototype.then = function(onFulfilled, onRejected) {
  const promise = this;
  // 每次返回一个promise
  return new Promise(function (resolve, reject) {
    // 此方法是创建几个then则生成几个handle，这样就能保证没一个then都执行到
    function handle(value) {
      // 如果成功函数存在则执行成功函数如果不存在则直接返回value
      const ret =
        (typeof onFulfilled === "function" && onFulfilled(value)) || value;

      // 判断是不是promise 对象
      if (ret && typeof ret["then"] == "function") {
        ret.then(
          function(value) {
            resolve(value);
          },
          function(reason) {
            reject(reason);
          }
        );
      } else {
        resolve(ret);
      }
    }

    function errback(reason) {
      reason =
        (typeof onRejected === "function" && onRejected(reason)) || reason;
      reject(reason);
    }

    if (promise._status === "PENDING") {
      promise._resolves.push(handle);
      promise._rejects.push(errback);
    } else if (promise._status === "FULFILLED") {
      this._resolves = (this._resolves || []).concat(handle);
      // 状态改变后的then操作，立刻执行
      resolve(promise._value);
    } else if (promise._status === "REJECTED") {
      this._reason = (this._reason || []).concat(errback);
      errback(promise._reason);
    }
  });
};

Promise.prototype.catch = function(onRejected) {
  return this.then(undefined, onRejected);
};

exports.Promise = Promise;
